/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using EvaluationException = System.Qizx.Api.EvaluationException;
using System.Qizx.XQuery;
using IntegerValue = System.Qizx.XQuery.Dt.IntegerValue;
namespace System.Qizx.XQuery.Fn
{
	
	/// <summary>  Implementation of function fn:index-of.</summary>
	public class IndexOf:Function
	{
		public override Prototype[] Protos
		{
			get
			{
				return protos;
			}
			
		}

        internal static Prototype[] protos;
		
		public class Exec:Function.Call
		{
			public override XQValue eval(Focus focus, EvalContext context)
			{
				XQValue src = args[0].eval(focus, context);
				XQItem item = args[1].evalAsItem(focus, context);
				System.Globalization.CompareInfo collator = getCollator(args.Length <= 2?null:args[2], focus, context);
				context.at(this);
				return new Sequence(src, item, context, collator);
			}
		}
		
		public class Sequence:IntegerValue, ComparisonContext
		{
			public override long ValueAsInteger
			{
				get
				{
					return position;
				}
				
			}
			virtual public int ImplicitTimezone
			{
				get
				{
					return context.ImplicitTimezone;
				}
				
			}
			internal XQValue source;
			internal XQItem searched;
			internal int position = 0;
			internal EvalContext context;
			internal System.Globalization.CompareInfo collator;
			
			internal Sequence(XQValue source, XQItem searched, EvalContext context, System.Globalization.CompareInfo collator)
			{
				this.source = source;
				this.searched = searched;
				this.context = context;
				this.collator = collator;
			}
			
			public override bool Next()
			{
				for (; source.Next(); )
				{
					++position;
					if (source.CompareTo(searched, this, 0) == 0)
						return true;
				}
				return false;
			}
			
			public override long getValue()
			{
				return position;
			}
			
			public override XQValue BornAgain()
			{
				return new Sequence(source.BornAgain(), searched, context, collator);
			}
			
			// --- comp context:
			public virtual bool emptyGreatest()
			{
				return context.emptyGreatest();
			}
			
			public virtual System.Globalization.CompareInfo getCollator()
			{
				return collator;
			}
		}
		static IndexOf()
		{
			protos = new Prototype[]{Prototype.fn("index-of", XQType.INTEGER.star, typeof(Exec)).arg("seqParam", XQType.ANY_ATOMIC_TYPE.star).arg("srchParam", XQType.ANY_ATOMIC_TYPE), Prototype.fn("index-of", XQType.INTEGER.star, typeof(Exec)).arg("seqParam", XQType.ANY_ATOMIC_TYPE.star).arg("srchParam", XQType.ANY_ATOMIC_TYPE).arg("collationLiteral", XQType.STRING)};
		}
	}
}